#include "GameEngine.h"
#include "Zona.h"
#include "Scene.h"

GameEngine *GameEngine::m_instance=NULL;

bool showHelp=true, smoothScroll=true;

const sf::Input &GameEngine::GetInput() const{
	return window.GetInput();
}

GameEngine &GameEngine::GetEngine(){
	if(!m_instance){
		m_instance = new GameEngine();
	}
	return *m_instance;
}
//Constructor del GameEngine
GameEngine::GameEngine(){
	exit = false;	
}
//Destructor del GameEngine
GameEngine::~GameEngine(){	
	
}

//Iniciamos el GameEngine
//-----* Crea el Window o Ventana con los parametros ingresados
//-----* Configura el Window o Ventana creada
void GameEngine::Init(unsigned w, unsigned h){
	//---*Creamos la ventana de la aplicacion y
	//---*configuramos algunas opciones
	window.Create(sf::VideoMode(w,h), "Metroid PROGVIDII");
	//window.SetFramerateLimit(60);
	//window.UseVerticalSync(true);
	m_sceneToDelete = NULL;
	m_currentScene = NULL;	

	player1=new Samus ("../Data/Sprites/samus4.png",10,5);
    player1->SetType("SAMUS");
    player1->SetName("SAMUS");
}

//Loop General de todo el GameEngine

void GameEngine::Loop(){

	sf::Clock clock;
	float elapsedTime;
	sf::Event event;
	
	
	// el bucle de juego
	clock.Reset();
	while(m_currentScene != NULL && !exit){
		if(clock.GetElapsedTime()<0.05){
		elapsedTime=clock.GetElapsedTime();
		clock.Reset();}
		else
		{
			elapsedTime=0.0001f;
			clock.Reset();
		}
	
		//---*Actualiza la Escena Actual.
		m_currentScene->Update(elapsedTime);		
		//---*Dibuja la Escena Actual.
		window.Clear(sf::Color(0,0,0));
		m_currentScene->Render(window);
		window.Display();		

		// manejo de escenas: si hubo algun cambio de escena, lo hace efectivo
		if (m_mustUpdateCurrentScene){
			m_mustUpdateCurrentScene=false;
			// si hay alguna escena por borrar/desinicializar, lo hace
			if (m_sceneToDelete != NULL){
				m_sceneToDelete->Cleanup();
				delete m_sceneToDelete;
				m_sceneToDelete = NULL;
			}
			// pone como escena actual la escena del frente de la cola
			if (m_sceneQueue.size()>0)
				m_currentScene = m_sceneQueue.front();
			else
				m_currentScene = NULL;
		}

		// procesa los eventos y llama a la funcion de eventos de la escena
		while(window.GetEvent(event)) {
						
			if(event.Type == event.Closed){
				window.Close();
				exit = true;
			}			
			else{
				m_currentScene->ProcessEvent(event);
			}
		}

		

	}	
}


void GameEngine::ChangeScene(Scene *s){
	PopScene();		// quita la escena actual de la cola
	PushScene(s);	// empuja otra escena en su posicion
	m_mustUpdateCurrentScene = true;	// activa la bandera para que se actualicen los punteros de escenas
}

void GameEngine::PushScene(Scene *s){
	s->Init();
	m_sceneQueue.push_front(s);
	m_mustUpdateCurrentScene = true;
	//m_sceneToDelete = NULL;
}

void GameEngine::PopScene(){
	m_sceneToDelete = m_sceneQueue.front();
	m_sceneQueue.pop_front();
	m_mustUpdateCurrentScene = true;

	
}

void GameEngine::AppendScene(Scene *s){
	if ( m_sceneQueue.size() == 0)
		m_currentScene = s;
	m_sceneQueue.push_back(s);
	s->Init();
	//m_sceneToDelete = NULL;
}

void GameEngine::EndCurrentScene(){
	PopScene();
}



void GameEngine::Exit(){
	exit = true;
}
